package com.moonshineproject.plugin.console
{
	import com.moonshineproject.IDEModel;
	import com.moonshineproject.plugin.IPlugin;
	import com.moonshineproject.plugin.PluginBase;
	import com.moonshineproject.plugin.console.setting.SpecialKeySetting;
	import com.moonshineproject.plugin.console.view.ConsoleModeEvent;
	import com.moonshineproject.plugin.console.view.ConsoleView;
	import com.moonshineproject.plugin.menu.MenuPlugin;
	import com.moonshineproject.plugin.settings.ISettingsProvider;
	import com.moonshineproject.plugin.settings.vo.BooleanSetting;
	import com.moonshineproject.plugin.settings.vo.ISetting;
	
	import flash.events.Event;
	import flash.events.KeyboardEvent;

	public class ConsolePlugin extends PluginBase implements IPlugin, ISettingsProvider
	{
		
		private var consoleView:ConsoleView;
				
		private var _consolePopsOver:Boolean = true;
		public function get consolePopsOver():Boolean
		{
			return _consolePopsOver;
		}
		public function set consolePopsOver(v:Boolean):void
		{
			_consolePopsOver = v;
			if (consoleView) consoleView.consolePopOver = v;
		}
		  
		public var consoleTriggerKeyPropertyName:String = "charCode";
		public var consoleTriggerKeyValue:int = 167;
		
		private var mode:String = "";
		
		override public function get name():String { return "Console Plugin"; }
		override public function get author():String { return "Erik Pettersson & Moonshine Project Team"; }
		override public function get description():String { return "Bottom console functionality."; }
		
		override public function activate():void
		{
			consoleView = new ConsoleView();
			consoleView.consolePopOver = consolePopsOver;
			
			if (IDEModel.getInstance().mainView)
			{
				IDEModel.getInstance().mainView.addChild(consoleView);
			}
			if (consoleView.stage)
			{
				addKeyListener();
			}
			else
			{
				consoleView.addEventListener(Event.ADDED_TO_STAGE, addKeyListener);
			}
			
			dispatcher.addEventListener(ConsoleOutputEvent.EVENT_CONSOLE_OUTPUT, addOutput);
			dispatcher.addEventListener(ConsoleModeEvent.CHANGE, changeMode);
			
			registerCommand("clear", clearCommand);
			registerCommand("hide", hideCommand);
			registerCommand("exit", exitCommand);
			registerCommand("help", helpCommand);
			
			// Get commands from view
			consoleView.commandLine.addEventListener(ConsoleCommandEvent.EVENT_COMMAND, execCommand);
		}
		
		override public function deactivate():void
		{
			if (consoleView && consoleView.parent)
			{
				consoleView.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
				consoleView.parent.removeChild(consoleView);
			}
			
			unregisterCommand("clear");
			unregisterCommand("hide");
			unregisterCommand("exit");
			unregisterCommand("help");
			
			dispatcher.removeEventListener(ConsoleOutputEvent.EVENT_CONSOLE_OUTPUT, addOutput);
			dispatcher.removeEventListener(ConsoleModeEvent.CHANGE, changeMode);
		}
		
		override public function get activated():Boolean
		{
			return (consoleView != null);
		}
		
		private function addKeyListener(event:Event=null):void
		{
			consoleView.stage.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
		}
		
		private function handleKeyDown(event:KeyboardEvent):void
		{
			if (event[consoleTriggerKeyPropertyName] == consoleTriggerKeyValue)
			{
				event.preventDefault();
				toggleConsole();
			}
		}
		
		public function getSettingsList():Vector.<ISetting>
		{
			return Vector.<ISetting>([
				new SpecialKeySetting(this, "consoleTriggerKey", "Console trigger key"),
				new BooleanSetting(this, "consolePopsOver", "Console should glide over editor")
			]);
		}
		
		private function toggleConsole():void
		{
			if (consoleView.stage.focus != consoleView.commandLine)
			{
				consoleView.commandLine.setFocus();
			}
			else
			{
				IDEModel.getInstance().activeEditor.setFocus();		
			}
		}
		

		private function changeMode(e:ConsoleModeEvent):void 
		{
			mode = e.mode;
			consoleView.commandPrefix.text = " "+mode+">"
		}
		
		private function execCommand(event:ConsoleCommandEvent):void
		{
			if (mode == "")	
			{
				if (console::commands[event.command])
				{
					console::commands[event.command](event.args);	
				}
				else
				{
					print("%s: command not found", event.command);
				}
			} 
			else 
			{
				// Command is an argument in a mode
				var args:Array = [event.command];
				args = args.concat(event.args);
				console::commands[mode](args);
			}
		}
			
		private function addOutput(event:ConsoleOutputEvent):void
		{
			var numNewLines:int = consoleView.history.appendText(event.text);
			
			if (event.hideOtherOutput)
			{ 
				consoleView.history.dataProvider = "";
			}
			
			if (consoleView.history.numVisibleLines < numNewLines)
			{
				consoleView.setOutputHeightByLines(numNewLines);
			}
		}
		
		
		public function clearCommand(args:Array):void
		{
			dispatcher.dispatchEvent( new ConsoleOutputEvent("", true) );
		}
		
		public function exitCommand(args:Array):void
		{
			dispatcher.dispatchEvent( new Event(MenuPlugin.MENU_QUIT_EVENT) );
		}
		
		public function hideCommand(args:Array):void
		{
			consoleView.setOutputHeight(0);
			var model:IDEModel = IDEModel.getInstance();
			if (model.activeEditor) model.activeEditor.setFocus();
		}
		
		public function helpCommand(args:Array):void
		{
			var halp:String = "Available commands:\n";
			for (var cmd:String in console::commands)
			{
				halp += cmd + "\n";
			}
			halp = halp.substr(0, halp.length-1);
			outputMsg(halp);
		}
	}
}